// Copyright (c) 2005  INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of cgal-python; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with cgal-python.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $Id: Py_Polyhedron_3.cpp 167 2007-11-02 15:36:54Z spion $
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal-python/trunk/cgal-python/bindings/Polyhedron/Py_Polyhedron_3.cpp $
//
// Author(s)     : Naceur Meskini
//=========================================================================

// include ====================================================================
#include <CGAL/basic.h>
#include <include/Kernels.h>
#include <CGAL/Polyhedron_3.h>
#include "Py_Polyhedron_3_doc.h"

#include <boost/python.hpp>
#include <boost/cstdint.hpp>
#include <include/iterator.h>
#include <list>


// Using =======================================================================
using namespace boost::python;

// Declarations ================================================================
namespace  {

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(normalized_border_is_valid_overloads_0_1, normalized_border_is_valid, 0, 1)

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(is_valid_overloads_0_2, is_valid, 0, 2)
}// namespace 
//=====================
template < class iterator,class Handle,class Polyhedron_3>
Handle_to_py_iterator<iterator,Handle> py_vertices(Polyhedron_3& Poly)
{
	std::pair< iterator , iterator > p( Poly.vertices_begin(), Poly.vertices_end() );
	return Handle_to_py_iterator<iterator,Handle>(p);
}
//=====================

template < class iterator,class Handle,class Polyhedron_3>
Handle_to_py_iterator<iterator,Handle> py_facets(Polyhedron_3& Poly)
{
	std::pair< iterator , iterator > p( Poly.facets_begin(), Poly.facets_end() );
	return Handle_to_py_iterator<iterator,Handle>(p);
}
//=====================

template < class iterator,class Handle,class Polyhedron_3>
Handle_to_py_iterator<iterator,Handle> py_halfedges(Polyhedron_3& Poly)
{
	std::pair< iterator , iterator > p( Poly.halfedges_begin(), Poly.halfedges_end() );
	return Handle_to_py_iterator<iterator,Handle>(p);
}
//=====================

template < class iterator,class Handle,class Polyhedron_3>
Handle_to_py_iterator<iterator,Handle> py_border_halfedges(Polyhedron_3& Poly)
{
	std::pair< iterator , iterator > p( Poly.border_halfedges_begin(), Poly.halfedges_end() );
	return Handle_to_py_iterator<iterator,Handle>(p);
}
//=====================
template < class iterator,class Polyhedron_3>
simple_python_iterator<iterator> py_points(Polyhedron_3& Poly)
{
	std::pair< iterator , iterator > p( Poly.points_begin(), Poly.points_end() );
	return simple_python_iterator<iterator>(p);
}
//=====================

template < class iterator,class Polyhedron_3>
simple_python_iterator<iterator> py_edges(Polyhedron_3& Poly)
{
	std::pair< iterator , iterator > p( Poly.edges_begin(), Poly.edges_end() );
	return simple_python_iterator<iterator>(p);
}
//=====================

template < class iterator,class Polyhedron_3>
simple_python_iterator<iterator> py_border_edges(Polyhedron_3& Poly)
{
	std::pair< iterator , iterator > p( Poly.border_edges_begin(), Poly.edges_end() );
	return simple_python_iterator<iterator>(p);
}
//=====================
template < class iterator,class Polyhedron_3>
simple_python_iterator<iterator> py_planes(Polyhedron_3& Poly)
{
	std::pair< iterator , iterator > p( Poly.planes_begin(), Poly.planes_end() );
	return simple_python_iterator<iterator>(p);
}
//=====================
template < class Polyhedron_3,class Halfedge_handle>
bool is_triangle(const Polyhedron_3& Poly,const Halfedge_handle& half_edge)
{
	return Poly.is_triangle(half_edge);
}
//=====================
template < class Polyhedron_3,class Halfedge_handle>
bool is_tetrahedron(const Polyhedron_3& Poly,const Halfedge_handle& half_edge)
{
	return Poly.is_tetrahedron(half_edge);
}
//=====================
template<class kernel>
void Py_Polyhedron_3()
{
 	typedef CGAL::Polyhedron_3<kernel> 					Polyhedron_3;
 	typedef typename Polyhedron_3::Halfedge_handle 		Halfedge_handle;
 	typedef typename Polyhedron_3::Halfedge_iterator 	Halfedge_iterator;
	
	typedef typename Polyhedron_3::Vertex_handle 	Vertex_handle;
	typedef typename Polyhedron_3::Vertex_iterator 	Vertex_iterator;
	typedef typename Polyhedron_3::Facet_handle 	Facet_iterator;
	typedef typename Polyhedron_3::Facet_handle 	Facet_handle;
	typedef typename Polyhedron_3::Point_iterator 	Point_iterator;
	typedef typename Polyhedron_3::Edge_iterator 	Edge_iterator;
	typedef typename Polyhedron_3::Plane_iterator 	Plane_iterator;


 	typedef typename kernel::Point_3 Point_3;

    class_< Polyhedron_3 >("Polyhedron_3", Polyhedron_3_doc,init< Polyhedron_3& >())
        .def(init< optional< const kernel& > >())
        .def(init< size_t, size_t, size_t, optional< const kernel& > >())
        .def("reserve", &Polyhedron_3::reserve,reserve_doc)
        .def("make_tetrahedron", (Halfedge_handle (Polyhedron_3::*)() )&Polyhedron_3::make_tetrahedron,make_tetrahedron_doc)
        .def("make_tetrahedron", (Halfedge_handle (Polyhedron_3::*)(const Point_3&, const Point_3&, const Point_3&, const Point_3&) )&Polyhedron_3::make_tetrahedron)
        .def("make_triangle", (Halfedge_handle (Polyhedron_3::*)() )&Polyhedron_3::make_triangle,make_triangle_doc)
        .def("make_triangle", (Halfedge_handle (Polyhedron_3::*)(const Point_3&, const Point_3&, const Point_3&) )&Polyhedron_3::make_triangle)
//         .def("get_allocator", &Polyhedron_3::get_allocator)
        .def("size_of_vertices", &Polyhedron_3::size_of_vertices,size_of_vertices_doc)
        .def("size_of_halfedges", &Polyhedron_3::size_of_halfedges,size_of_halfedges_doc)
        .def("size_of_facets", &Polyhedron_3::size_of_facets,size_of_facets_doc)
        .def("empty", &Polyhedron_3::empty,empty_doc)
        .def("capacity_of_vertices", &Polyhedron_3::capacity_of_vertices,capacity_of_vertices_doc)
        .def("capacity_of_halfedges", &Polyhedron_3::capacity_of_halfedges,capacity_of_halfedges_doc)
        .def("capacity_of_facets", &Polyhedron_3::capacity_of_facets,capacity_of_facets_doc)
        .def("bytes", &Polyhedron_3::bytes,bytes_doc)
        .def("bytes_reserved", &Polyhedron_3::bytes_reserved,bytes_reserved_doc)
//         .def("traits", (const kernel& (Polyhedron_3::*)() const)&Polyhedron_3::traits, return_value_policy< copy_const_reference >())
        .def("is_closed", &Polyhedron_3::is_closed,is_closed_doc)
        .def("is_pure_bivalent", (bool (Polyhedron_3::*)() const)&Polyhedron_3::is_pure_bivalent,is_pure_bivalent_doc)
        .def("is_pure_trivalent", (bool (Polyhedron_3::*)() const)&Polyhedron_3::is_pure_trivalent,is_pure_trivalent_doc)
        .def("is_pure_triangle", (bool (Polyhedron_3::*)() const)&Polyhedron_3::is_pure_triangle,is_pure_triangle_doc)
        .def("is_pure_quad", (bool (Polyhedron_3::*)() const)&Polyhedron_3::is_pure_quad,is_pure_quad_doc)
        .def("is_triangle", &is_triangle< Polyhedron_3,Halfedge_handle>,is_triangle_doc)
        .def("is_tetrahedron", &is_tetrahedron< Polyhedron_3,Halfedge_handle>,is_tetrahedron_doc)
        .def("split_facet", &Polyhedron_3::split_facet,split_facet_doc)
        .def("join_facet", &Polyhedron_3::join_facet,join_facet_doc)
        .def("split_vertex", &Polyhedron_3::split_vertex,split_vertex_doc)
        .def("join_vertex", &Polyhedron_3::join_vertex,join_vertex_doc)
        .def("split_edge", &Polyhedron_3::split_edge,split_edge_doc)
        .def("flip_edge", &Polyhedron_3::flip_edge,flip_edge_doc)
        .def("create_center_vertex", &Polyhedron_3::create_center_vertex,create_center_vertex_doc)
        .def("erase_center_vertex", &Polyhedron_3::erase_center_vertex,erase_center_vertex_doc)
        .def("split_loop", &Polyhedron_3::split_loop,split_loop_doc)
        .def("join_loop", &Polyhedron_3::join_loop,join_loop_doc)
        .def("make_hole", &Polyhedron_3::make_hole,make_hole_doc)
        .def("fill_hole", &Polyhedron_3::fill_hole,fill_hole_doc)
        .def("add_vertex_and_facet_to_border", &Polyhedron_3::add_vertex_and_facet_to_border,add_vertex_and_facet_to_border_doc)
        .def("add_facet_to_border", &Polyhedron_3::add_facet_to_border,add_facet_to_border_doc)
        .def("erase_facet", &Polyhedron_3::erase_facet,erase_facet_doc)
        .def("erase_connected_component", &Polyhedron_3::erase_connected_component,erase_connected_component_doc)
        .def("clear", &Polyhedron_3::clear,clear_doc)
        .def("erase_all", &Polyhedron_3::erase_all,erase_all_doc)
//         .def("delegate", &Polyhedron_3::delegate)
        .def("size_of_border_halfedges", &Polyhedron_3::size_of_border_halfedges,size_of_border_halfedges_doc)
        .def("size_of_border_edges", &Polyhedron_3::size_of_border_edges,size_of_border_edges_doc)
        .def("normalized_border_is_valid", &Polyhedron_3::normalized_border_is_valid, normalized_border_is_valid_overloads_0_1(normalized_border_is_valid_doc))
        .def("normalize_border", &Polyhedron_3::normalize_border,normalize_border_doc)
        .def("inside_out", &Polyhedron_3::inside_out,inside_out_doc)
        .def("is_valid", &Polyhedron_3::is_valid, is_valid_overloads_0_2(is_valid_doc))
		.add_property("vertices", &py_vertices<Vertex_iterator,Vertex_handle,Polyhedron_3>)
		.add_property("facets", &py_facets<Facet_iterator,Facet_handle,Polyhedron_3>)
		.add_property("points", &py_points<Point_iterator,Polyhedron_3>)
		.add_property("edges", &py_edges<Edge_iterator,Polyhedron_3>)
		.add_property("border_edges", &py_border_edges<Edge_iterator,Polyhedron_3>)
		.add_property("planes", &py_planes<Plane_iterator,Polyhedron_3>)
		.add_property("halfedges", &py_halfedges<Halfedge_iterator,Halfedge_handle,Polyhedron_3>)
		.add_property("border_halfedges", &py_border_halfedges<Halfedge_iterator,Halfedge_handle,Polyhedron_3>)
    ;

	Handle_to_py_iterator<Vertex_iterator,Vertex_handle>::declare("Vertex_iterator");
	Handle_to_py_iterator<Halfedge_iterator,Halfedge_handle>::declare("Halfedge_iterator");
	Handle_to_py_iterator<Facet_iterator,Facet_handle>::declare("Facet_iterator");

	simple_python_iterator<Edge_iterator>::declare("Edge_iterator");
	simple_python_iterator<Point_iterator>::declare("Point_iterator");
	simple_python_iterator<Plane_iterator>::declare("Plane_iterator");

// 	simple_python_iterator<OutputItVertices>::declare("OutputItVertices");
// 	simple_python_iterator<OutputItCells>::declare("OutputItCells");
// 
// 	simple_python_iterator<Vertex_handle>::declare("All_vertices_iterator");
// 	simple_python_iterator<All_facets_iterator>::declare("All_facets_iterator");
// 	simple_python_iterator<All_edges_iterator>::declare("All_edges_iterator");
// 	simple_python_iterator<Cell_handle>::declare("All_cells_iterator");
// 
// 	simple_python_circulator<Facet_circulator>::declare("Facet_circulator");
// 	circulator_to_py_iterator<Cell_circulator,Cell_handle>::declare("Cell_circulator");

 
}

void export_Polyhedron_3()
{
	Py_Polyhedron_3<K>();
}
